const { getDbPool } = require('../infra/dbClient');
const db = getDbPool();
const { getLogger } = require('../logger');
const logger = getLogger('models.monitorModel');

/**
 * 监控数据模型（增强版）
 * 
 * 支持功能：
 * - 基础监控数据存储
 * - 用户行为事件序列记录
 * - 会话管理
 * - 操作回溯数据支持
 * - 错误与操作序列关联
 */
class MonitorModel {
    
    /**
 * 插入性能数据到专门的性能表
 */
static async insertPerformanceData(sessionId, performanceData, userId = null) {
    
    try {
        const sql = `
            INSERT INTO monitor_performance 
            (session_id, user_id, page_url, page_title, reporttype, category, type, 
             dns, tcp, ttfb, fpt, load_time, fcp, lcp, fid, cls, tbt, long_task_count, 
             resource_count, data, timestamp)
            VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
        `;
        
        const params = [
            sessionId,
            userId || null,
            performanceData.pageUrl || performanceData.url || '',
            performanceData.pageTitle || '',
            'performance',
            performanceData.category || 'page_performance',
            performanceData.type || 'page_load',
            performanceData.metrics?.dns || 0,
            performanceData.metrics?.tcp || 0,
            performanceData.metrics?.ttfb || 0,
            performanceData.metrics?.fpt || 0,
            performanceData.metrics?.load || 0,
            performanceData.metrics?.fcp || 0,
            performanceData.metrics?.lcp || 0,
            performanceData.metrics?.fid || 0,
            performanceData.metrics?.cls || 0,
            performanceData.metrics?.tbt || 0,
            performanceData.metrics?.longTaskCount || 0,
            performanceData.metrics?.resourceCount || 0,
            JSON.stringify(performanceData),
            performanceData.timestamp || Date.now()
        ];
        
        const [result] = await db.execute(sql, params);
        return { success: true, insertId: result.insertId };
    } catch (error) {
        logger.error('插入性能数据失败', { error });
        return { success: false, error: error };
    }
}
    
    /**
 * 插入用户行为事件
 */
static async insertBehaviorEvent(sessionId, eventData, userId = null) {
    try {
        const sql = `
            INSERT INTO monitor_behavior_events
            (session_id, user_id, sequence_id, operation_id, type, event_type, category,
             element_info, action_time, page_url, page_title, event_data, timestamp)
            VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
        `;
        
        const eventType = eventData.eventType || eventData.type || 'unknown';
        
        const params = [
            sessionId,
            userId || null,
            eventData.sequenceId || null,
            eventData.operationId || null,
            eventType,
            eventType, // 兼容字段，保持与type一致
            eventData.category || 'general',
            JSON.stringify(eventData.elementInfo || {}),
            eventData.actionTime || eventData.timestamp || Date.now(),
            eventData.pageUrl || '',
            eventData.pageTitle || '',
            JSON.stringify(eventData),
            eventData.timestamp || Date.now()
        ];
        
        const [result] = await db.execute(sql, params);
        return { success: true, insertId: result.insertId };
    } catch (error) {
        logger.error('插入行为事件失败', { error });
        return { success: false, error: error };
    }
}
    
    /**
 * 更新会话信息
 */
static async updateSessionInfo(sessionId, userId = null, userAgent = '', pageUrl = '') {
    try {
        // 先尝试更新，如果不存在则插入
        const updateSql = `
            UPDATE monitor_sessions
            SET user_id = ?, last_activity = ?, last_page_url = ?
            WHERE session_id = ?
        `;
        
        const [updateResult] = await db.execute(updateSql, [userId || null, Date.now(), pageUrl, sessionId]);
        
        // 如果没有更新任何记录，则插入新记录
        if (updateResult.affectedRows === 0) {
            const insertSql = `
                INSERT INTO monitor_sessions
                (session_id, user_id, user_agent, start_time, last_activity, first_page_url, last_page_url)
                VALUES (?, ?, ?, ?, ?, ?, ?)
            `;
            
            await db.execute(insertSql, [
                sessionId,
                userId || null,
                userAgent,
                Date.now(),
                Date.now(),
                pageUrl,
                pageUrl
            ]);
        }
        
        return { success: true };
    } catch (error) {
        logger.error('更新会话信息失败', { error });
        return { success: false, error: error };
    }
}
    
    /**
     * 批量插入监控数据
     */
    static async batchInsertMonitorData(reportData) {
        
        const { sessionId, data, timestamp, url, userId } = reportData;
        
        // 调试：记录调用信息
        logger.info('批量插入监控数据', { sessionId, dataLength: data.length });
        
        if (!data || data.length === 0) {
            return { insertedCount: 0 };
        }
        
        // 清理 sessionId 中的非法字符
        const cleanedSessionId = sessionId.replace(/[^\x20-\x7E]/g, '');
        const now = timestamp || Date.now();
        
        // 先更新会话信息
        const firstItem = data[0];
        await this.updateSessionInfo(cleanedSessionId, userId, firstItem.userAgent, url || firstItem.pageUrl);
        
        // 分类处理数据：基础监控、行为事件、性能数据
        const monitorDataItems = [];
        const behaviorEventItems = [];
        const performanceItems = [];
        
        data.forEach(item => {
            // 根据不同的数据类型提取适当的字段
            let message = '';
            let errorType = '';
            let stack = '';
            let filename = '';
            let position = '';
            let playbackInfo = null;
            
            // 处理自定义事件
            if (item.type === 'custom_event' && item.eventName) {
                message = `Custom Event: ${item.eventName}`;
            }
            // 处理错误事件
            else if (item.reporttype === 'error' || item.message) {
                message = item.message || '';
                errorType = item.errorType || '';
                stack = item.stack || '';
                filename = item.filename || '';
                position = item.position || '';
                // 检查是否有回溯数据
                if (item.playbackInfo) {
                    playbackInfo = JSON.stringify(item.playbackInfo);
                }
            }
            // 处理性能数据 - 单独存储
            else if (item.reporttype === 'performance') {
                performanceItems.push(item);
                return; // 跳过常规处理
            }
            // 处理行为事件 - 单独存储
            else if (item.reporttype === 'behavior') {
                behaviorEventItems.push(item);
            }
            // 其他类型数据
            else {
                message = item.description || '';
            }
            
            // 确保不超过字段长度限制
            message = message.substring(0, 1000);
            stack = stack.substring(0, 2000);
            if (playbackInfo && playbackInfo.length > 3000) {
                playbackInfo = playbackInfo.substring(0, 3000);
            }
            
            // 构建基础监控数据
            monitorDataItems.push([
                cleanedSessionId,
                userId || null,
                item.sequenceId || null,
                item.operationId || null,
                item.reporttype || 'monitor',// 上报类型
                item.type || 'unknown',
                item.category || 'general',
                message,
                errorType || item.type || 'unknown',
                item.pageUrl || url || '',
                item.pageTitle || '',
                item.userAgent || '',
                stack,
                filename,
                position,
                playbackInfo,
                JSON.stringify(item),  // 完整数据JSON
                item.timestamp || now  // 使用数据自带的时间戳或当前时间
            ]);
        });
        
        // 处理基础监控数据
        let monitorDataResult = { insertedCount: 0 };
        if (monitorDataItems.length > 0) {
            // 使用MySQL多值插入语法
            const placeholders = monitorDataItems.map(() => '(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)').join(', ');
            
            const sql = `
                INSERT INTO monitor_data 
                (session_id, user_id, sequence_id, operation_id, reporttype, type, category, message, error_type, 
                 page_url, page_title, user_agent, stack, filename, position, playback_info, data, timestamp) 
                VALUES ${placeholders}
            `;
            
            // 扁平化参数数组以用于预处理语句
            const flattenedParams = [].concat(...monitorDataItems);
        
            try {
                logger.info('执行SQL批量插入基础监控数据', { dataCount: monitorDataItems.length });
                const [result] = await db.execute(sql, flattenedParams);
                monitorDataResult = {
                    insertedCount: result.affectedRows,
                    insertId: result.insertId
                };
            } catch (error) {
                logger.error('批量插入基础监控数据失败', { error });
                
                // 如果批量插入失败，尝试单条插入以便定位问题
                let successCount = 0;
                for (const singleData of monitorDataItems) {
                    try {
                        const singleSql = `
                            INSERT INTO monitor_data 
                            (session_id, user_id, sequence_id, operation_id, reporttype, type, category, message, error_type, 
                             page_url, page_title, user_agent, stack, filename, position, playback_info, data, timestamp) 
                            VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
                        `;
                        await db.execute(singleSql, singleData);
                        successCount++;
                    } catch (singleError) {
                        logger.error('单条插入失败', { data: { sessionId: singleData[0], message: singleData[1] }, error: singleError });
                    }
                }
                
                monitorDataResult = {
                    insertedCount: successCount,
                    partialSuccess: true,
                    error: error
                };
            }
        }
        
        // 处理行为事件数据
        let behaviorSuccessCount = 0;
        for (const eventItem of behaviorEventItems) {
            const result = await this.insertBehaviorEvent(cleanedSessionId, eventItem, userId);
            if (result.success) behaviorSuccessCount++;
        }
        
        // 处理性能数据
        let performanceSuccessCount = 0;
        for (const perfItem of performanceItems) {
            const result = await this.insertPerformanceData(cleanedSessionId, perfItem, userId);
            if (result.success) performanceSuccessCount++;
        }
        
        // 汇总结果
        const totalInserted = monitorDataResult.insertedCount + behaviorSuccessCount + performanceSuccessCount;
        
        return {
            insertedCount: totalInserted,
            monitorData: monitorDataResult.insertedCount,
            behaviorEvents: behaviorSuccessCount,
            performanceData: performanceSuccessCount,
            partialSuccess: monitorDataResult.partialSuccess,
            error: monitorDataResult.error
        };
    }
    
    /**
     * 获取监控数据列表
     */
    static async getMonitorDataList(page = 1, limit = 50, filters = {}) {
        const offset = (page - 1) * limit;
        let whereClause = 'WHERE 1=1';
        let params = [];
        
        // 类型过滤
        if (filters.type) {
            whereClause += ' AND type = ?';
            params.push(filters.type);
        }
        
        
        // 页面URL过滤
        if (filters.pageUrl) {
            whereClause += ' AND page_url LIKE ?';
            params.push(`%${filters.pageUrl}%`);
        }
        
        // 时间范围过滤
        if (filters.startTime && filters.endTime) {
            whereClause += ' AND timestamp BETWEEN ? AND ?';
            params.push(filters.startTime, filters.endTime);
        }
        
        // 会话ID过滤
        if (filters.sessionId) {
            whereClause += ' AND session_id = ?';
            params.push(filters.sessionId);
        }
        
        // 用户ID过滤
        if (filters.userId) {
            whereClause += ' AND user_id = ?';
            params.push(filters.userId);
        }
        
        // 分类过滤
        if (filters.category) {
            whereClause += ' AND category = ?';
            params.push(filters.category);
        }
        
        // 操作ID过滤（用于关联业务操作）
        if (filters.operationId) {
            whereClause += ' AND operation_id = ?';
            params.push(filters.operationId);
        }
        
        // 上报类型过滤
        if (filters.reporttype) {
            whereClause += ' AND reporttype = ?';
            params.push(filters.reporttype);
        }
        
        const sql = `
            SELECT 
                id, 
                session_id, 
                user_id,
                sequence_id,
                operation_id,
                reporttype,
                type, 
                category,
                message,
                error_type,
                page_url,
                page_title,
                user_agent,
                stack,
                filename,
                position,
                playback_info,
                data, 
                timestamp, 
                created_at
            FROM monitor_data
            ${whereClause}
            ORDER BY timestamp DESC
            LIMIT ${db.escape(limit)} OFFSET ${db.escape(offset)}
        `;
        
        const [rows] = await db.execute(sql, params);
        
        // 总数查询
        const countSql = `
            SELECT COUNT(*) as total 
            FROM monitor_data
            ${whereClause}
        `;
        const [countResult] = await db.execute(countSql, params);
        
        return {
            list: rows,
            total: countResult[0].total,
            page,
            limit
        };
    }
    
    /**
 * 获取错误统计
 */
static async getErrorStats(startTime, endTime) {
    try {
        // 优先尝试调用存储过程
        const [result] = await db.execute(
            'CALL get_error_summary(?, ?)', 
            [startTime, endTime]
        );
        return result[0];
    } catch (error) {
        // 如果存储过程调用失败，使用基础查询
        logger.warn('存储过程调用失败，使用基础查询', { error });
        
        const sql = `
            SELECT 
                reporttype,
                type,
                error_type,
                category,
                COUNT(*) as error_count,
                COUNT(DISTINCT session_id) as affected_sessions,
                COUNT(DISTINCT user_id) as affected_users
            FROM monitor_data
            WHERE reporttype = 'error'
              AND timestamp BETWEEN ? AND ?
            GROUP BY reporttype, type, error_type, category
            ORDER BY error_count DESC
        `;
        
        const [rows] = await db.execute(sql, [startTime, endTime]);
        return rows;
    }
}
    
    /**
     * 获取操作回溯数据
     */
    static async getPlaybackData(sessionId, sequenceId = null) {
        let whereClause = 'WHERE session_id = ?';
        const params = [sessionId];
        
        if (sequenceId) {
            whereClause += ' AND sequence_id = ?';
            params.push(sequenceId);
        }
        
        const sql = `
            SELECT 
                sequence_id,
                operation_id,
                type,
                category,
                element_info,
                action_time,
                event_data
            FROM monitor_behavior_events
            ${whereClause}
            ORDER BY action_time ASC
        `;
        
        const [rows] = await db.execute(sql, params);
        return rows;
    }
    
    /**
     * 获取会话详情
     */
    static async getSessionDetail(sessionId) {
        // 获取会话基本信息
        const sessionSql = `
            SELECT * FROM monitor_sessions
            WHERE session_id = ?
        `;
        const [sessionRows] = await db.execute(sessionSql, [sessionId]);
        
        if (sessionRows.length === 0) {
            return null;
        }
        
        // 获取会话中的行为事件
        const eventsSql = `
            SELECT * FROM monitor_behavior_events
            WHERE session_id = ?
            ORDER BY action_time ASC
        `;
        const [eventsRows] = await db.execute(eventsSql, [sessionId]);
        
        // 获取会话中的错误信息
        const errorsSql = `
            SELECT * FROM monitor_data
            WHERE session_id = ? AND type = 'error'
            ORDER BY timestamp ASC
        `;
        const [errorsRows] = await db.execute(errorsSql, [sessionId]);
        
        // 获取会话中的性能数据
        const performanceSql = `
            SELECT * FROM monitor_performance
            WHERE session_id = ?
            ORDER BY timestamp ASC
        `;
        const [performanceRows] = await db.execute(performanceSql, [sessionId]);
        
        return {
            sessionInfo: sessionRows[0],
            events: eventsRows,
            errors: errorsRows,
            performance: performanceRows
        };
    }
    
    /**
 * 获取性能统计
 */
static async getPerformanceStats(startTime, endTime) {
    try {
        // 优先尝试调用存储过程
        const [result] = await db.execute(
            'CALL get_performance_summary(?, ?)', 
            [startTime, endTime]
        );
        return result[0];
    } catch (error) {
        // 如果存储过程调用失败，使用基础查询
        logger.warn('存储过程调用失败，使用基础查询', { error });
        
        // 从专用性能表获取统计，效率更高
        const sql = `
            SELECT 
                AVG(load_time) as avg_load_time,
                AVG(fpt) as avg_fpt,
                AVG(ttfb) as avg_ttfb,
                AVG(dns) as avg_dns,
                AVG(tcp) as avg_tcp,
                AVG(fcp) as avg_fcp,
                AVG(lcp) as avg_lcp,
                AVG(fid) as avg_fid,
                AVG(cls) as avg_cls,
                AVG(tbt) as avg_tbt,
                COUNT(*) as sample_count
            FROM monitor_performance
            WHERE timestamp BETWEEN ? AND ?
        `;
        
        const [rows] = await db.execute(sql, [startTime, endTime]);
        return rows[0];
    }
}
    
    /**
 * 获取用户行为统计
 */
static async getBehaviorStats(startTime, endTime) {
    try {
        // 优先尝试调用存储过程
        const [result] = await db.execute(
            'CALL get_behavior_summary(?, ?)', 
            [startTime, endTime]
        );
        return result[0];
    } catch (error) {
        // 如果存储过程调用失败，使用基础查询
        logger.warn('存储过程调用失败，使用基础查询', { error });
        
        const sql = `
            SELECT 
                type,
                category,
                COUNT(*) as event_count,
                COUNT(DISTINCT session_id) as unique_sessions,
                COUNT(DISTINCT user_id) as unique_users,
                ROUND(COUNT(*) / COUNT(DISTINCT session_id), 2) as avg_per_session
            FROM monitor_behavior_events
            WHERE timestamp BETWEEN ? AND ?
            GROUP BY type, category
            ORDER BY event_count DESC
        `;
        
        const [rows] = await db.execute(sql, [startTime, endTime]);
        return rows;
    }
}
    
    /**
 * 清理过期数据
 */
static async cleanExpiredData(daysToKeep = 7) {
    const expireTime = Date.now() - (daysToKeep * 24 * 60 * 60 * 1000);
    
    try {
        // 优先调用存储过程进行全面清理
        const [result] = await db.execute(
            'CALL clean_monitor_data(?)', 
            [daysToKeep]
        );
        
        return {
            success: true,
            message: `已清理 ${daysToKeep} 天前的过期数据`,
            affectedRows: result[0]?.[0]?.affected_rows || 0,
            daysKept: daysToKeep
        };
    } catch (error) {
        // 如果存储过程调用失败，回退到基本清理
        logger.warn('存储过程清理失败，使用基本清理方式', { error });
        
        // 清理各个表的数据
        const tables = ['monitor_data', 'monitor_performance', 'monitor_behavior_events'];
        let totalDeleted = 0;
        
        for (const table of tables) {
            const [result] = await db.execute(
                `DELETE FROM ${table} WHERE timestamp < ?`, 
                [expireTime]
            );
            totalDeleted += result.affectedRows;
        }
        
        // 清理已结束且过期的会话
        await db.execute(
            `DELETE FROM monitor_sessions WHERE last_activity < ? AND end_time IS NOT NULL`, 
            [expireTime]
        );
        
        return {
            success: true,
            message: '使用基本方式清理完成',
            deletedCount: totalDeleted
        };
    }
}
    
    /**
     * 获取会话列表
     */
    static async getSessionList(page = 1, limit = 20) {
        const offset = (page - 1) * limit;
        
        const sql = `
            SELECT 
                ms.session_id,
                ms.user_id,
                ms.user_agent,
                ms.start_time,
                ms.last_activity,
                ms.page_url as last_url,
                (SELECT COUNT(*) FROM monitor_behavior_events WHERE session_id = ms.session_id) as event_count,
                (SELECT COUNT(*) FROM monitor_data WHERE session_id = ms.session_id AND type = 'error') as error_count
            FROM monitor_sessions ms
            ORDER BY ms.last_activity DESC
            LIMIT ${db.escape(limit)} OFFSET ${db.escape(offset)}
        `;
        
        const [rows] = await db.execute(sql, []);
        
        // 总数查询
        const countSql = `
            SELECT COUNT(*) as total
            FROM monitor_sessions
        `;
        const [countResult] = await db.execute(countSql);
        
        return {
            list: rows,
            total: countResult[0].total,
            page,
            limit
        };
    }
}

module.exports = MonitorModel;

